package com.ioe.p2p.service;

import com.ioe.p2p.util.MgrUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

import static com.ioe.p2p.util.CommonUtil.enableConsolePrintln;
import static com.ioe.p2p.util.CommonUtil.log;

/**
 * @author tanbo
 * @create 2023/10/8
 */
public class P2PProcessor extends Processor{

    /**
     * 服务器地址
     */
    private static final InetSocketAddress isd = new InetSocketAddress("localhost", 8000);

    /**
     * UDP通道
     */
    private DatagramChannel dc;

    /**
     * 选择器
     */
    private Selector selector;

    /**
     * 容量大小
     */
    private static final int CAPACITY = 1024 * 64;

    /**
     * 数据接收容器
     */
    private final ByteBuffer buffer = ByteBuffer.allocate(CAPACITY);

    private final StringBuilder sb = new StringBuilder();

    public static Processor getProcessor() {
        return Instance.processor;
    }

    private static final class Instance{
        private static final Processor processor = new P2PProcessor();
    }

    @Override
    public Processor init(DatagramChannel dc, Selector selector) {
        this.dc = dc;
        this.selector = selector;
        return this;
    }

    @Override
    public Processor begin() throws IOException {
        dc.configureBlocking(false);
        dc.register(selector, SelectionKey.OP_READ);
        log("请输入用户名：");
        MgrUtil.send(
                enableConsolePrintln(),
                dc,
                isd
        );
        return this;
    }

    @Override
    public void complete() throws IOException {
        for (;;){
            selector.select();
            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
            while (iter.hasNext()) {
                SelectionKey sk = iter.next();
                if (sk.isReadable()) {
                    dealReadEvent(sk);
                }
                iter.remove();
            }
        }

    }

    /**
     * 处理读取事件
     * @param sk 事件key
     * @throws IOException e
     */
    private void dealReadEvent(SelectionKey sk) throws IOException {
        SocketAddress sa = dc.receive(buffer);
        DatagramChannel dc = (DatagramChannel) sk.channel();
        int read = dc.read(buffer);
        if (read != -1){
            buffer.flip();
            sb.append(new String(buffer.array(), StandardCharsets.UTF_8));
            String text;
            if ((text = sb.toString()).contains("\r\n\r\n")){
                System.out.println(text);
            }
            buffer.clear();
        }
    }
}
